/** *************************************************************************
 *  @file       TSNInsight.c
 *  @brief	    P2P应用与TSNInsight应用通信的接口
 *  @date		2022/03/29 
 *  @author		junshuai.li
 *  @version	0.0.1 
编写人：李军帅
version0.0.1
1、初始版本			  
****************************************************************************/
#include "../include/ptp_tsninsight.h"
#include "../include/8021AS_PTP.h"


u8 G_NET_STATE = 0;
u64 report_period = 100;//单位ms，开始赋值为最大值


//opensync可读地址合法性判断,不合法返回-1，寄存器地址返回1，状态表地址返回2
int opensync_read_addr_validity_judgment(u32 base_addr, u16 num)
{

	//判断是否为合法的状态表地址
	if((base_addr >= OPENSYNC_SYNC_STATE_ADDR) && ((base_addr+2*num)<= (OPENSYNC_SYNC_STATE_ADDR + 2*MAX_NODE_NUM)))
	{
		return 2;
	}
	else if((base_addr >= OPENSYNC_REG_ADDR) && ((base_addr+num-1)<= OPENSYNC_SYNC_PERIOD))
	{
		return 1;
	}
	else
	{
		return -1;
	}

	return -1;
}


void remote_get_opensync_data(u8 *remote_pkt, opensync_reg_data* register_data, sync_state_table* state_table)
{
	printf("this is remote_get_opensync_data() !!!!!!\n");

	remote_manage_get_res_pkt *tmp_data = NULL ;
	unsigned int addr_offset = 0;
	unsigned int base_addr = 0;
	unsigned int num = 0;
	u8* tmp_pkt = NULL;
	
	int ret  = -1;
	int pkt_len = 0;

	tmp_data = (remote_manage_get_res_pkt *)(remote_pkt + UDP_HEAD_LEN);
	base_addr = ntohl(tmp_data->base_addr);
	num = ntohs(tmp_data->num);

	ret = opensync_read_addr_validity_judgment(base_addr, num);
	printf("ret=%d\n",ret);

	if(ret == -1) //读地址出错
	{
		tmp_data->num = 0;
		pkt_len = sizeof(remote_manage_get_res_pkt);
	}
	else if(ret == 1)//读寄存器地址空间
	{
		addr_offset = base_addr - OPENSYNC_REG_ADDR;

		printf("ctrl_mode=%x ,master_mid=%x,protocol_type=%x \n",ntohl(register_data->ctrl_mode),ntohl(register_data->master_mid),ntohl(register_data->protocol_type));
		printf("sync_period=%x ,ver_num=%x\n",ntohl(register_data->sync_period),ntohl(register_data->ver_num));
		
		tmp_pkt = (u8*)register_data + 4*addr_offset;
		memcpy((u8*)&(tmp_data->value[0]),tmp_pkt,4*num);
		pkt_len = sizeof(remote_manage_get_res_pkt)+ num*4;
	}
	else if(ret == 2)
	{
		addr_offset = base_addr - OPENSYNC_SYNC_STATE_ADDR;

		tmp_pkt = (u8*)state_table + 4*addr_offset;
		memcpy((u8*)&(tmp_data->value[0]),tmp_pkt,4*num);
		pkt_len = sizeof(remote_manage_get_res_pkt)+ num*4;
	}

	tmp_data->header.sub_type = REMOTE_GET_RES;
	
	tsninsight_msg_sender((u8*)tmp_data, pkt_len); //不需要UDP头
}

//OpenSync可写地址合法性判断
int opensync_write_addr_validity_judgment(u32 base_addr, u16 num)
{
	int ret = 0;
	
	printf("base_addr = %x ,num = %x ! \n", base_addr,num);

	if((base_addr != OPENSYNC_SYNC_PERIOD) || (num != 1))
	{
		ret = -1;
	}

	return ret;
}


void remote_set_opensync_data(u8 *remote_pkt, opensync_reg_data* register_data, sync_state_table* state_table)
{
	printf("this is remote_get_opensync_data() !!!!!!\n");
	remote_manage_set_req_pkt* tmp_data; //保存北向应用报文中的数据
	u8 * tmp_pkt = NULL;
	int ret;
	//申请空间，用于构造配置报文
	u8 *pkt = NULL;

	tmp_pkt = remote_pkt + UDP_HEAD_LEN;
	tmp_data = (remote_manage_set_req_pkt*)tmp_pkt;

	ret = opensync_write_addr_validity_judgment(ntohl(tmp_data->base_addr), ntohs(tmp_data->num));
	
	if(ret == -1) //写地址有问题
	{
		printf("switch opensync addr error, reject this cmd !\n");
		tmp_data->num = 0;
	}
	else //写数据
	{
		register_data->sync_period = tmp_data->value[0];

		pkt = (u8 *)malloc(MAX_PKT_LEN);
		if (NULL == pkt)
		{
			printf("remote_set_opensync_data, malloc buf fail\n");
			return ;
		}

		bzero(pkt, MAX_PKT_LEN);

		// 配置同步周期
		ret = cfg_reg_value(register_data->master_mid, pkt, htonl(register_data->sync_period), htonl(SYNC_PERIOD_REG));

		// 释放申请的空间
		if(pkt != NULL)
		{
			free(pkt);
		}
			
		if (ret == -1)
		{
			printf("cfg_sync_period fail \n");
			return;
		}
		
	}

	tmp_data->header.sub_type = REMOTE_SET_RES;
	memcpy(remote_pkt, (u8*)tmp_data, sizeof(remote_manage_set_res_pkt));
	
	tsninsight_msg_sender((u8*)remote_pkt, sizeof(remote_manage_set_res_pkt)); //不需要UDP头 

	return;
}



void remote_pkt_process(u8 *pkt,u16 pkt_len, opensync_reg_data* register_data, sync_state_table* state_table)
{
	remote_manage_pkt *tmp_pkt = (remote_manage_pkt *)(pkt + UDP_HEAD_LEN);
	
	printf("this is remote_pkt_process() !!!!!!\n");
	//printf("protocol_type=%d,master_mid=%d,sync_period=%d\n",ntohl(register_data->protocol_type),ntohl(register_data->master_mid),ntohl(register_data->sync_period));

	if(tmp_pkt->header.sub_type == REMOTE_GET_REQ)
	{
		if((ntohs)(((remote_manage_get_req_pkt *)tmp_pkt)->taskid) == REMOTE_TASK_OPENSYNC)
		{
			//获取OpenSync地址空间的数据
			printf("*********************** get OpenSync data *************************************\n");
			remote_get_opensync_data(pkt, register_data, state_table);
		}
		else
		{
			remote_manage_get_res_pkt *tmp_data = NULL ;
			tmp_data = (remote_manage_get_res_pkt *)(pkt + UDP_HEAD_LEN);

			tmp_data->num = 0;
			pkt_len = sizeof(remote_manage_get_res_pkt);

			tmp_data->header.sub_type = REMOTE_GET_RES;
	
			tsninsight_msg_sender((u8*)tmp_data, pkt_len); //不需要UDP头

		}
	}
	else if(tmp_pkt->header.sub_type == REMOTE_SET_REQ)
	{
		if((ntohs)(((remote_manage_set_req_pkt *)tmp_pkt)->taskid) == REMOTE_TASK_OPENSYNC)
		{
			//设置OpenSync地址空间的数据
			printf("*********************** set OpenSync data *************************************\n");
			remote_set_opensync_data(pkt, register_data, state_table);
		}
		else
		{
			remote_manage_set_req_pkt *tmp_data = NULL ;
			tmp_data = (remote_manage_set_req_pkt *)(pkt + UDP_HEAD_LEN);

			tmp_data->num = 0;
			pkt_len = sizeof(remote_manage_set_req_pkt);

			tmp_data->header.sub_type = REMOTE_SET_RES;
	
			tsninsight_msg_sender((u8*)tmp_data, pkt_len); //不需要UDP头
		}
	}
	else
	{
		printf("recv unknow pkt type!\n");
	}
	
	return;
}
